const logger = require("../utils/logger")
const mysqlUtil = require("../utils/mysqlUtil")
const commonModule = require("./common")
const util = require("../utils/util")

const moment = require('moment')
const redisUtil = require("../utils/redisUtil")

async function getLingdao(uid) {
    let sql = `
        SELECT
            con_department.zhijie_lingdao,
            tb_user_zhijie.name zhijie_lingdao_name,
            con_department.fenguan_lingdao,
            tb_user_fenguan.name fenguan_lingdao_name,
            con_department.zhuyao_lingdao,
            tb_user_zhuyao.name zhuyao_lingdao_name
        FROM
            tb_user
        INNER JOIN con_department ON con_department.id = tb_user.department
        LEFT JOIN tb_user tb_user_zhijie ON tb_user_zhijie.uid = con_department.zhijie_lingdao
        LEFT JOIN tb_user tb_user_fenguan ON tb_user_fenguan.uid = con_department.fenguan_lingdao
        LEFT JOIN tb_user tb_user_zhuyao ON tb_user_zhuyao.uid = con_department.zhuyao_lingdao
        WHERE tb_user.uid = ? LIMIT 1
    `

    let res = await mysqlUtil.execute(sql, [uid])
    return res[0] || null
}

async function agreeTaskInfo(io, socket, params, taskInfo, callback) {

    let pos = taskInfo.pos

    let tb = ''
    let subject = ''
    if (taskInfo.typ == 0) { // 请假申请
        tb = 'tb_user_vacation_apply'
        subject = '请假申请'
    } else if (taskInfo.typ == 1) { // 出差申请
        tb = 'tb_user_chuchai_apply'
        subject = '出差申请'
    } else if (taskInfo.typ == 2) { // 加班申请
        tb = 'tb_jiaban_apply'
        subject = '加班申请'
    } else if (taskInfo.typ == 3) { // 入职申请
        tb = 'tb_entry_apply'
        subject = '入职申请'
    } else if (taskInfo.typ == 4) { // 转正申请
        tb = 'tb_user_zhuanzheng_apply'
        subject = '转正申请'
    } else if (taskInfo.typ == 5) { // 离职申请
        tb = 'tb_user_departure_apply'
        subject = '离职申请'
    } else if (taskInfo.typ == 6) { // 督办申请
        tb = 'tb_user_duban_apply'
        subject = '督办申请'
    } else if (taskInfo.typ == 7) { // 会议室申请
        tb = 'tb_meeting_room_apply'
        subject = '会议室申请'
    } else if (taskInfo.typ == 8) { // 接待申请
        tb = 'tb_user_jiedai_apply'
        subject = '接待单申请'
    } else if (taskInfo.typ == 9) { // 车辆加油
        tb = 'tb_user_jiayou_apply'
        subject = '车辆加油申请'
    } else if (taskInfo.typ == 10) { // 用车申请
        tb = 'tb_user_yongche_apply'
        subject = '用车申请'
    } else if (taskInfo.typ == 11) { // 用印申请
        tb = 'tb_user_yongyin_apply'
        subject = '用印申请'
    } else if (taskInfo.typ == 13) { // 采购申请
        tb = 'tb_user_caigou_apply'
        subject = '采购申请'
    } else if (taskInfo.typ == 14) { // 物资领用
        tb = 'tb_user_wuzilingyong_apply'
        subject = '物资领用申请'
    } else if (taskInfo.typ == 15) { // 合同审批
        tb = 'tb_user_hetong_shenpi'
        subject = '合同审批申请'
    } else if (taskInfo.typ == 16) { // 招标审核
        tb = 'tb_user_zhaobiao_shenhe'
        subject = '招标审核申请'
    } else if (taskInfo.typ == 17) { // 传阅文件
        tb = 'tb_user_chuanyue_apply'
        subject = '传阅文件申请'
    } else if (taskInfo.typ == 18) { // 文件流转
        tb = 'tb_user_liuzhuan_apply'
        subject = '公文流转申请'
    } else if (taskInfo.typ == 19) { // 补卡申请
        tb = 'tb_user_buka_apply'
        subject = '补卡申请'
    }

    // 查询申请信息
    let sql2 = 'SELECT * FROM ?? WHERE id = ? LIMIT 1'
    let res2 = await mysqlUtil.execute(sql2, [tb, taskInfo.relevenceId])
    if (res2.length == 0) return callback({ code: -1, message: '申请信息不存在' })
    let applyInfo = res2[0]
    // 没有这个审核位置
    if (!applyInfo.auditors || !applyInfo.auditors['auditor' + pos]) return callback({ code: -1, message: '申请信息错误' })
    // 检查是不是自己的申请
    if (applyInfo.auditors['auditor' + pos].uid != socket.uid) return callback({ code: -1, message: '申请无法处理' })

    // 检查上个人拒绝了没
    if (applyInfo.auditors['auditor' + (pos - 1)] && applyInfo.auditors['auditor' + (pos - 1)].sta != 1) return callback({ code: -1, message: '申请已被拒绝' })

    // 查询申请人的信息
    let sql3 = 'SELECT * FROM tb_user WHERE uid = ? LIMIT 1'
    let res3 = await mysqlUtil.execute(sql3, [applyInfo.uid])
    if (res3.length == 0) return callback({ code: -1, message: '申请人信息不存在' })
    let applyUserInfo = res3[0]

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 检查是不是重复处理的情况 重复处理的要看下个人是否处理了
    let auditors = applyInfo.auditors
    
    // 有下个审核人 判断下个审核人是不是处理了 没有下个审核人 则判断审核人是否都处理了
    if (auditors['auditor' + (pos + 1)]) {
        if (auditors['auditor' + (pos + 1)].sta != 0) return callback({ code: -1, message: '下个审核人已处理' })
    } else {
        let chengbanren = applyInfo.chengbanren || {}
        let chengbanDid = false
        for (let k in chengbanren) {
            if (chengbanren[k].sta != 0) {
                chengbanDid = true
                break
            }
        }

        if (chengbanDid) return callback({ code: -1, message: '流程已被处理' })
        applyInfo.chengbanren = {}
        await mysqlUtil.execute('UPDATE ?? SET chengbanren = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(applyInfo.chengbanren), taskInfo.relevenceId])
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // 更新申请的信息
    applyInfo.auditors['auditor' + pos].sta = 1
    applyInfo.auditors['auditor' + pos].ts = Date.now()
    applyInfo.auditors['auditor' + pos].msg = params.msg
    applyInfo.auditors['auditor' + pos].chepai = params.chepai || ''

    // 保存到服务器
    applyInfo.sta = 0
    await mysqlUtil.execute('UPDATE ?? SET auditors = ?, sta = 0 WHERE id = ? LIMIT 1', [tb, JSON.stringify(applyInfo.auditors), taskInfo.relevenceId])

    // 用车申请要处理一下车牌信息
    if (taskInfo.typ == 10 && applyInfo.auditors['auditor' + pos].chepai) {
        await mysqlUtil.execute("UPDATE tb_user_yongche_apply SET chepai = ? WHERE id = ? LIMIT 1", [applyInfo.auditors['auditor' + pos].chepai, taskInfo.relevenceId])
    }

    // 如果是最后一个审核人 且还是审核中的状态 审核通过
    logger.debug('apply info', applyInfo)
    if (pos == Object.getOwnPropertyNames(applyInfo.auditors).length - 1) {
    // if (applyInfo.auditSta == 1 && pos == Object.getOwnPropertyNames(applyInfo.auditors).length - 1) {
        logger.debug('审核结束')

        // 更新审核状态为审核通过
        await mysqlUtil.execute('UPDATE ?? SET auditSta = 2 WHERE id = ? LIMIT 1', [tb, applyInfo.id])

        // 督办单 给责任部门的领导添加承办任务
        if (taskInfo.typ == 6 && applyInfo.dutyInfo && applyInfo.dutyInfo.length > 0) {
            let dutyInfo = applyInfo.dutyInfo
            let chengbanObj = {}
            for (let i = 0; i != dutyInfo.length; i++) {
                chengbanObj['chengbanren' + i] = {
                    uid: dutyInfo[i].departLingdao,
                    name: dutyInfo[i].departLingdaoName,
                    positionName: dutyInfo[i].departName,
                    sta: 0
                }
                // 给承办人发送任务
                await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ? AND isChengban = ?', [taskInfo.typ, applyInfo.id, i, 1])
                logger.info('承办删除任务1', [taskInfo.typ, applyInfo.id, i, 1])
                await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
                    uid: dutyInfo[i].departLingdao,
                    typ: taskInfo.typ,
                    relevenceId: applyInfo.id,
                    pos: i,
                    title: subject,
                    content: subject + '请跟进督办任务',
                    sta: 0,
                    isChengban: 1,
                    createTime: Date.now()
                }])
                io.in(dutyInfo[i].departLingdao + '-app').emit('TASK-CHANGE')
                io.in(dutyInfo[i].departLingdao + '-app').emit('TASK-NEW')
                io.in(dutyInfo[i].departLingdao + '-web').emit('TASK-CHANGE')
                io.in(dutyInfo[i].departLingdao + '-web').emit('TASK-NEW')
                util.sendReminderSmsToUser(dutyInfo[i].departLingdao, '督办单', '待跟进')
            }

            // 将承办人更新到申请表中
            await mysqlUtil.execute('UPDATE ?? SET chengbanren = ?, chengbanSta = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(chengbanObj), 1, applyInfo.id])

            // 更新任务状态 
            await mysqlUtil.execute('UPDATE tb_user_task SET sta = 1 WHERE id = ? LIMIT 1', [taskInfo.id])

            // 通知前端刷新角标
            io.in(socket.uid + '-app').emit('TASK-CHANGE')
            io.in(socket.uid + '-web').emit('TASK-CHANGE')

            return callback({ code: 0, message: 'success' })
        }

        // 如果是18 公文流转 且是位置3需要选定一个或两个分管领导 或者部门负责人 作为承办人
        if (taskInfo.typ == 18 && taskInfo.pos == 2) {

            let users = params.users || []
            let departs = params.departs || []

            if (users.length == 0 && departs.length == 0) return callback({code: -1, message: '参数缺失'})

            logger.debug('apply info', applyInfo)
            logger.debug('task info', taskInfo)
            let chengbanObj = {}

            if (users.length > 0) {
                for (let i = 0; i != users.length; i++) {
                    chengbanObj['chengbanren' + i] = {
                        uid: users[i].uid,
                        name: users[i].name,
                        positionName : users[i].positionName,
                        sta: 0,
                        fenguan: 1
                    }
    
                    // 给承办人发送任务
                    await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ? AND isChengban = ?', [taskInfo.typ, applyInfo.id, i, 1])
                    logger.info('承办删除任务2', [taskInfo.typ, applyInfo.id, i, 1])
                    await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
                        uid: users[i].uid,
                        typ: taskInfo.typ,
                        relevenceId: applyInfo.id,
                        pos: i,
                        title: applyInfo.biaoti,
                        content: applyInfo.biaoti,
                        sta: 0,
                        isChengban: 1,
                        createTime: Date.now()
                    }])
                    io.in(users[i].uid + '-app').emit('TASK-CHANGE')
                    io.in(users[i].uid + '-app').emit('TASK-NEW')
                    io.in(users[i].uid + '-web').emit('TASK-CHANGE')
                    io.in(users[i].uid + '-web').emit('TASK-NEW')
    
                    // 分管领导 加到关联表中
                    await mysqlUtil.execute('INSERT INTO tb_user_liuzhuan_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                        uid: users[i].uid,
                        relevenceId: applyInfo.id,
                        updateTime: Date.now()
                    }, Date.now()])
    
                    let smsContent = subject
                    let file1Name = ''
                    let attaches = applyInfo.attaches || []
                    if (attaches.length > 0) {
                        file1Name = attaches[0].name
                    }
                    if (file1Name) {
                        if (file1Name.length > 20) {
                            file1Name = file1Name.slice(0, 19) + '...'
                        }
                        smsContet = smsContent + '【' + file1Name + '】'
                    }
    
                    util.sendReminderSmsToUser(users[i].uid, smsContent, '待跟进')
                }
            } else if (departs.length > 0) {
                for (let i = 0; i != departs.length; i++) {
                    chengbanObj['chengbanren' + i] = {}
                    chengbanObj['chengbanren' + i].uid = departs[i].departLingdao
                    chengbanObj['chengbanren' + i].departId = departs[i].departId
                    chengbanObj['chengbanren' + i].name = departs[i].departLingdaoName
                    chengbanObj['chengbanren' + i].positionName = departs[i].departName
                    chengbanObj['chengbanren' + i].sta = 0
    
                    // 发送任务
                    await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ? AND isChengban = ?', [taskInfo.typ, applyInfo.id, i, 1])
                    logger.info('承办删除任务3', [taskInfo.typ, applyInfo.id, i, 1])
                    await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
                        uid: departs[i].departLingdao,
                        typ: taskInfo.typ,
                        relevenceId: applyInfo.id,
                        title: applyInfo.biaoti,
                        pos: i,
                        isChengban: 1,
                        content: applyInfo.biaoti,
                        sta: 0,
                        createTime: Date.now()
                    }])
                    io.in( departs[i].departLingdao + '-app').emit('TASK-CHANGE')
                    io.in( departs[i].departLingdao + '-app').emit('TASK-NEW')
                    io.in( departs[i].departLingdao + '-web').emit('TASK-CHANGE')
                    io.in( departs[i].departLingdao + '-web').emit('TASK-NEW')
    
                    // 公文流转 需要添加到公文流转关联表中
                    await mysqlUtil.execute('INSERT INTO tb_user_liuzhuan_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                        uid: departs[i].departLingdao,
                        relevenceId: applyInfo.id,
                        updateTime: Date.now()
                    }, Date.now()])
    
                    let smsContent = '公文流转'
                    let file1Name = ''
                    let attaches = applyInfo.attaches || []
                    if (attaches.length > 0) {
                        file1Name = attaches[0].name
                    }
                    if (file1Name) {
                        if (file1Name.length > 20) {
                            file1Name = file1Name.slice(0, 19) + '...'
                        }
                        smsContent = smsContent + '【' + file1Name + '】'
                    }
    
                    util.sendReminderSmsToUser(departs[i].departLingdao, smsContent, '待跟进')
                }
            }

            // 将承办人更新到申请表中
            await mysqlUtil.execute('UPDATE ?? SET chengbanren = ?, chengbanSta = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(chengbanObj), 1, applyInfo.id])

            // 更新任务状态 
            await mysqlUtil.execute('UPDATE tb_user_task SET sta = 1 WHERE id = ? LIMIT 1', [taskInfo.id])

            // 通知前端刷新角标
            io.in(socket.uid + '-app').emit('TASK-CHANGE')
            io.in(socket.uid + '-web').emit('TASK-CHANGE')

            return callback({ code: 0, message: 'success' })
        }

        // 获取承办步骤
        let res = await mysqlUtil.execute('SELECT chengbanStep FROM con_eve WHERE eve_id = ? LIMIT 1', [taskInfo.typ])
        if (res.length == 0 || res[0].chengbanStep.length == 0) { // 没有承办步骤 直接结束
            logger.debug('没有承办步骤')
            await mysqlUtil.execute('UPDATE ?? SET sta = 1 WHERE id = ? LIMIT 1', [tb, applyInfo.id])
            // 插入通知
            await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                uid: applyInfo.uid, // 请假人的uid
                typ: taskInfo.typ,
                title: subject + '审核通过',
                content: '所有的审批已通过，' + subject + '审核已通过',
                sta: 0,
                resTyp: 3,
                relevenceId: applyInfo.id,
                createTime: Date.now()
            }])

            // 通知给申请人
            io.in(applyInfo.uid + '-app').emit('NOTIFICATION-CHANGE')
            io.in(applyInfo.uid + '-app').emit('NOTIFICATION-NEW')
            io.in(applyInfo.uid + '-web').emit('NOTIFICATION-CHANGE')
            io.in(applyInfo.uid + '-web').emit('NOTIFICATION-NEW')

            if (taskInfo.typ == 0) { // 请假要展开 开始时间和结束时间按天进行分割
                let infos = applyInfo.detail || []
                let uid = applyInfo.uid
                for (let i = 0; i != infos.length; i++) {
                    let day = infos[i].day
                    // 查询当天有没有打卡记录 没有则插入
                    let rr = await mysqlUtil.execute('SELECT qingjiaInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [uid, day])
                    if (rr.length == 0) {
                        let dakaInfo = { uid, day }
                        await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                    }
                    let qingjiaInfo = {start: infos[i].start, end: infos[i].end}

                    // 更新请假信息
                    await mysqlUtil.execute('UPDATE tb_user_daka SET qingjiaInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(qingjiaInfo), uid, day])
                }
            } else if (taskInfo.typ == 1) { // 出差要展开 展开到打卡信息中
                for (let i = 0; i != applyInfo.days; i++) {
                    let chuchairen = applyInfo.chuchairen || []
                    for (let j = 0; j != chuchairen.length; j++) {
                        let uid = chuchairen[j].uid
                        let day = moment(applyInfo.startDate).add(i, 'day').format('YYYY-MM-DD')
                        // 查询当天有没有打卡记录 没有则插入
                        let rr = await mysqlUtil.execute('SELECT chuchaiInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [uid, day])
                        if (rr.length == 0) {
                            let dakaInfo = { uid, day }
                            await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                        }
                        let chuchaiInfo = {id: applyInfo.id, start: moment(day).startOf('day').format('HH:mm:ss'), end: moment(day).endOf('day').format('HH:mm:ss')}

                        // 更新出差信息
                        await mysqlUtil.execute('UPDATE tb_user_daka SET chuchaiInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(chuchaiInfo), uid, day])
                    }
                }
            } else if (taskInfo.typ == 2) { // 加班要展开 并通知加班人
                let attenders = applyInfo.attenders

                // 为每一个加班的员工加入一条加班申请 方便进行考勤统计
                for (let i = 0; i != attenders.length; i++) {

                    let jiabanUid = attenders[i].uid
                    let day = moment(applyInfo.startTime).format('YYYY-MM-DD')
                    // 查询当天有没有打卡记录 没有则插入
                    let rr = await mysqlUtil.execute('SELECT jiabanInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [jiabanUid, day])
                    if (rr.length == 0) {
                        let dakaInfo = { uid: jiabanUid, day }
                        await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                    }
                    let jiabanInfo = {start: moment(applyInfo.startTime).format('YYYY-MM-DD HH:mm:ss'), end: moment(applyInfo.endTime).format('YYYY-MM-DD HH:mm:ss')}

                    // 更新加班信息
                    await mysqlUtil.execute('UPDATE tb_user_daka SET jiabanInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(jiabanInfo), jiabanUid, day])
                }
            } else if (taskInfo.typ == 19) { // 补卡申请设置为审核通过状态
                if (applyInfo.bukaType == 1) {
                    await mysqlUtil.execute('UPDATE tb_user_daka SET shangbanBukaSta = 2 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
                } else if (applyInfo.bukaType == 2) {
                    await mysqlUtil.execute('UPDATE tb_user_daka SET xiabanBukaSta = 2 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
                }
            }
        } else { // 解析承办步骤
            let chengbanSta = 0
            let chengbanren = []
            let lingdaos = await getLingdao(taskInfo.uid)
            let chengbanStep = res[0].chengbanStep
            logger.debug('解析承办步骤', chengbanStep)
            for (let i = 0; i != chengbanStep.length; i++) {
                let step = chengbanStep[i]
                if (step.typ == 'zhijie') {
                    if (lingdaos && lingdaos.zhijie_lingdao) {
                        let sql = `
                            SELECT 
                                con_position.name
                            FROM
                                tb_user
                                INNER JOIN con_position ON con_position.id = tb_user.position
                            WHERE
                                tb_user.id = ?
                            LIMIT 1
                        `
                        let res = await mysqlUtil.execute(sql, [lingdaos.zhijie_lingdao])
                        chengbanren.push({ uid: lingdaos.zhijie_lingdao, name: lingdaos.zhijie_lingdao_name, positionName: step.name || res[0].name, sta: 0 })
                    }
                } else if (step.typ == 'fenguan') {
                    if (lingdaos && lingdaos.fenguan_lingdao) {
                        let sql = `
                            SELECT 
                                con_position.name
                            FROM
                                tb_user
                                INNER JOIN con_position ON con_position.id = tb_user.position
                            WHERE
                                tb_user.id = ?
                            LIMIT 1
                        `
                        let res = await mysqlUtil.execute(sql, [lingdaos.fenguan_lingdao])
                        chengbanren.push({ uid: lingdaos.fenguan_lingdao, name: lingdaos.fenguan_lingdao_name, positionName: step.name || res[0].name, sta: 0 })
                    }
                } else if (step.type == 'zhuyao') {
                    if (lingdaos && lingdaos.zhuyao_lingdao) {
                        let sql = `
                            SELECT 
                                con_position.name
                            FROM
                                tb_user
                                INNER JOIN con_position ON con_position.id = tb_user.position
                            WHERE
                                tb_user.id = ?
                            LIMIT 1
                        `
                        let res = await mysqlUtil.execute(sql, [lingdaos.zhuyao_lingdao])
                        chengbanren.push({ uid: lingdaos.zhuyao_lingdao, name: lingdaos.zhuyao_lingdao_name, positionName: step.name || res[0].name, sta: 0 })
                    }
                } else if (step.typ == 'zhiding') {
                    let r = await mysqlUtil.execute(`
                            SELECT 
                                tb_user.uid,
                                tb_user.name, 
                                con_position.name positionName,
                                0 sta
                            FROM 
                                tb_user
                                INNER JOIN con_position ON con_position.id = tb_user.position
                            WHERE tb_user.uid = ? LIMIT 1
                        `, [step.val])
                    if (r.length != 0) {
                        // 是否是承办任务
                        r[0].task = step.task || '0'
                        r[0].positionName = step.name || step.positionName
                        chengbanren.push(r[0])
                    }
                }
            }

            let chengbanObj = {}
            for (let i = 0; i != chengbanren.length; i++) {
                if (chengbanren[i].task + '' == '1') { // 承办任务的
                    chengbanObj['chengbanren' + i] = chengbanren[i]
                    let content = applyUserInfo.name + '的' + applyInfo.biaoti || subject + '审核通过，请注意跟进'
                    if (taskInfo.typ == 11) {
                        content = applyInfo.wenjianming
                    }

                    // 给承办人发送任务
                    await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ? AND isChengban = ?', [taskInfo.typ, applyInfo.id, i, 1])
                    logger.info('承办删除任务4', [taskInfo.typ, applyInfo.id, i, 1])
                    await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
                        uid: chengbanren[i].uid,
                        typ: taskInfo.typ,
                        relevenceId: applyInfo.id,
                        pos: i,
                        title: content,
                        content,
                        sta: 0,
                        isChengban: 1,
                        createTime: Date.now()
                    }])
                    io.in(chengbanren[i].uid + '-app').emit('TASK-CHANGE')
                    io.in(chengbanren[i].uid + '-app').emit('TASK-NEW')
                    io.in(chengbanren[i].uid + '-web').emit('TASK-CHANGE')
                    io.in(chengbanren[i].uid + '-web').emit('TASK-NEW')

                    // 传阅文件 添加承办人到传阅文件关联表中
                    if (taskInfo.typ == 17) {
                        await mysqlUtil.execute('INSERT INTO tb_user_chuanyue_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                            uid: chengbanren[i].uid,
                            relevenceId: applyInfo.id,
                            updateTime: Date.now()
                        }, Date.now()])
                    }

                    // 传阅文件 添加承办人到传阅文件关联表中
                    if (taskInfo.typ == 18) {
                        await mysqlUtil.execute('INSERT INTO tb_user_liuzhuan_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                            uid: chengbanren[i].uid,
                            relevenceId: applyInfo.id,
                            updateTime: Date.now()
                        }, Date.now()])
                    }

                    // 公文流转和传阅文件需要添加文件名
                    let smsContent = subject
                    if (taskInfo.typ == 17 || taskInfo.typ == 18) {
                        let file1Name = ''
                        let attaches = applyInfo.attaches || []
                        if (attaches.length != 0) {
                            file1Name = attaches[0].name
                        }
                        if (file1Name) {
                            if (file1Name.length > 20) {
                                file1Name = file1Name.slice(0, 19) + '...'
                            }
                            smsContent = smsContent + '【' + file1Name + '】'
                        }
                    }

                    util.sendReminderSmsToUser(chengbanren[i].uid, smsContent, '待跟进')

                    chengbanSta = 1
                } else { // 直接发送通知的
                    let content = applyUserInfo.name + '的' + subject + '审核通过，请注意跟进'
                    if (taskInfo.typ == 11) {
                        content = applyInfo.wenjianming
                    }
                    await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                        uid: chengbanren[i].uid,
                        typ: taskInfo.typ,
                        title: subject,
                        content,
                        sta: 0,
                        resTyp: 3,
                        relevenceId: taskInfo.relevenceId,
                        createTime: Date.now()
                    }])
        
                    // 通知给承办人
                    io.in(chengbanren[i].uid + '-app').emit('NOTIFICATION-CHANGE')
                    io.in(chengbanren[i].uid + '-app').emit('NOTIFICATION-NEW')
                    io.in(chengbanren[i].uid + '-web').emit('NOTIFICATION-CHANGE')
                    io.in(chengbanren[i].uid + '-web').emit('NOTIFICATION-NEW')

                    // 公文流转和传阅文件需要添加文件名
                    let smsContent = subject
                    if (taskInfo.typ == 17 || taskInfo.typ == 18) {
                        let file1Name = ''
                        let attaches = applyInfo.attaches || []
                        if (attaches.length != 0) {
                            file1Name = attaches[0].name
                        }
                        if (file1Name) {
                            if (file1Name.length > 20) {
                                file1Name = file1Name.slice(0, 19) + '...'
                            }
                            smsContent = smsContent + '【' + file1Name + '】'
                        }
                    }

                    util.sendReminderSmsToUser(chengbanren[i].uid, smsContent, '待跟进')
                }
            }

            logger.debug('chengban sta', chengbanSta)
            // 没有承办任务 只有通知 直接结束
            if (chengbanSta == 0) {
                await mysqlUtil.execute('UPDATE ?? SET sta = 1 WHERE id = ? LIMIT 1', [tb, applyInfo.id])
                if (taskInfo.typ == 0) { // 请假要展开 开始时间和结束时间按天进行分割
                    let infos = applyInfo.detail || []
                    let uid = applyInfo.uid
                    for (let i = 0; i != infos.length; i++) {
                        let day = infos[i].day
                        // 查询当天有没有打卡记录 没有则插入
                        let rr = await mysqlUtil.execute('SELECT qingjiaInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [uid, day])
                        if (rr.length == 0) {
                            let dakaInfo = { uid, day }
                            await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                        }
                        let qingjiaInfo = {start: infos[i].start, end: infos[i].end}

                        // 更新请假信息
                        await mysqlUtil.execute('UPDATE tb_user_daka SET qingjiaInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(qingjiaInfo), uid, day])
                    }
                } else if (taskInfo.typ == 1) { // 出差要展开 展开到打卡信息中
                    for (let i = 0; i != applyInfo.days; i++) {
                        let chuchairen = applyInfo.chuchairen || []
                        for (let j = 0; j != chuchairen.length; j++) {
                            let uid = chuchairen[j].uid
                            let day = moment(applyInfo.startDate).add(i, 'day').format('YYYY-MM-DD')
                            // 查询当天有没有打卡记录 没有则插入
                            let rr = await mysqlUtil.execute('SELECT chuchaiInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [uid, day])
                            if (rr.length == 0) {
                                let dakaInfo = { uid, day }
                                await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                            }
                            let chuchaiInfo = {id: applyInfo.id, start: moment(day).startOf('day').format('HH:mm:ss'), end: moment(day).endOf('day').format('HH:mm:ss')}
        
                            // 更新出差信息
                            await mysqlUtil.execute('UPDATE tb_user_daka SET chuchaiInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(chuchaiInfo), uid, day])
                        }
                    }
                } else if (taskInfo.typ == 2) { // 加班要展开 并通知加班人
                    let attenders = applyInfo.attenders
                    for (let i = 0; i != attenders.length; i++) {
    
                        let jiabanUid = attenders[i].uid
                        let day = moment(applyInfo.startTime).format('YYYY-MM-DD')
                        // 查询当天有没有打卡记录 没有则插入
                        let rr = await mysqlUtil.execute('SELECT jiabanInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [jiabanUid, day])
                        if (rr.length == 0) {
                            let dakaInfo = { uid: jiabanUid, day }
                            await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                        }
                        let jiabanInfo = {start: moment(applyInfo.startTime).format('YYYY-MM-DD HH:mm:ss'), end: moment(applyInfo.endTime).format('YYYY-MM-DD HH:mm:ss')}
    
                        // 更新加班信息
                        await mysqlUtil.execute('UPDATE tb_user_daka SET jiabanInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(jiabanInfo), jiabanUid, day])
                    }
                } else if (taskInfo.typ == 8) { // 接待单要通知打包人
                    if (applyInfo.dabaoren && Array.isArray(applyInfo.dabaoren)) {
                        for (let i = 0; i != applyInfo.dabaoren.length; i++) {
                            let dabaoUid = applyInfo.dabaoren[i].uid
                            // 通知打包人
                            await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                                uid: dabaoUid, // 打包人的uid
                                typ: 8,
                                title: '请跟进接待打包',
                                content: '您有一个接待单需要打包',
                                sta: 0,
                                resTyp: 3,
                                relevenceId: applyInfo.id,
                                createTime: Date.now()
                            }])

                            io.in(dabaoUid + '-app').emit('NOTIFICATION-CHANGE')
                            io.in(dabaoUid + '-app').emit('NOTIFICATION-NEW')
                            io.in(dabaoUid + '-web').emit('NOTIFICATION-CHANGE')
                            io.in(dabaoUid + '-web').emit('NOTIFICATION-NEW')

                            util.sendReminderSmsToUser(dabaoUid, '接待单打包', '待处理')
                        }
                    }
                } else if (taskInfo.typ == 16) { // 招标文件审核 需要通知负责人
                    if (applyInfo.dabaoren && Array.isArray(applyInfo.dabaoren)) {
                        // 通知负责人
                        await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                            uid: applyInfo.fuzeren, // 打包人的uid
                            typ: 16,
                            title: '招标文件审核通过',
                            content: '招标文件审核通过',
                            sta: 0,
                            resTyp: 3,
                            relevenceId: applyInfo.id,
                            createTime: Date.now()
                        }])

                        io.in(applyInfo.fuzeren + '-app').emit('NOTIFICATION-CHANGE')
                        io.in(applyInfo.fuzeren + '-app').emit('NOTIFICATION-NEW')
                        io.in(applyInfo.fuzeren + '-web').emit('NOTIFICATION-CHANGE')
                        io.in(applyInfo.fuzeren + '-web').emit('NOTIFICATION-NEW')

                        util.sendReminderSmsToUser(applyInfo.fuzeren, '招标文件审核通过', '待处理')
                    }
                } else if (taskInfo.typ == 19) { // 补卡申请设置为审核通过状态
                    if (applyInfo.bukaType == 1) {
                        await mysqlUtil.execute('UPDATE tb_user_daka SET shangbanBukaSta = 2 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
                    } else if (applyInfo.bukaType == 2) {
                        await mysqlUtil.execute('UPDATE tb_user_daka SET xiabanBukaSta = 2 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
                    }
                }
            }

            // 将承办人更新到申请表中
            await mysqlUtil.execute('UPDATE ?? SET chengbanren = ?, chengbanSta = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(chengbanObj), chengbanSta, applyInfo.id])
        }
    } else if (applyInfo.auditSta == 1 && applyInfo.chexiao == 0) { // 还是审核中的状态 且没有被撤销 流转到下一个人
        let res = await mysqlUtil.execute('SELECT name FROM tb_user WHERE uid = ? LIMIT 1', [applyInfo.uid])
        if (res.length == 0) return callback({ code: -1, message: '用户不存在' })
        let name = res[0].name
        let content = name + '的' + subject + '需要您的审批'
        // 公文流转第三个人是转发，不是审批
        // if (taskInfo.typ == 18 && pos == 1) {
        //     content = applyInfo.biaoti
        // }

        // 传阅文件 需要添加到传阅文件关联表中
        if (taskInfo.typ == 17) {
            await mysqlUtil.execute('INSERT INTO tb_user_chuanyue_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                uid: applyInfo.auditors['auditor' + (pos + 1)].uid,
                relevenceId: applyInfo.id,
                updateTime: Date.now()
            }, Date.now()])
        }

        // 公文流转 需要添加到公文流转关联表中
        if (taskInfo.typ == 18) {
            await mysqlUtil.execute('INSERT INTO tb_user_liuzhuan_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                uid: applyInfo.auditors['auditor' + (pos + 1)].uid,
                relevenceId: applyInfo.id,
                updateTime: Date.now()
            }, Date.now()])
        }

        // 公文流转和传阅文件需要添加文件名
        let smsContent = subject
        if (taskInfo.typ == 17 || taskInfo.typ == 18) {
            content = applyInfo.biaoti
            let file1Name = ''
            let attaches = applyInfo.attaches || []
            if (attaches.length > 0) {
                file1Name = attaches[0].name || ''
            }
            if (file1Name) {
                if (file1Name.length > 20) {
                    file1Name = file1Name.slice(0, 19) + '...'
                }
                smsContent = smsContent + '【' + file1Name + '】'
            }
        }
        if (taskInfo.typ == 11) {
            content = applyInfo.wenjianming
        }
        await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ?', [taskInfo.typ, applyInfo.id, pos + 1])
        logger.info('审核删除任务', [taskInfo.typ, applyInfo.id, pos + 1])
        await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
            uid: applyInfo.auditors['auditor' + (pos + 1)].uid,
            typ: taskInfo.typ,
            relevenceId: applyInfo.id,
            pos: pos + 1,
            title: subject,
            content,
            sta: 0,
            createTime: Date.now()
        }])
        io.in(applyInfo.auditors['auditor' + (pos + 1)].uid + '-app').emit('TASK-CHANGE')
        io.in(applyInfo.auditors['auditor' + (pos + 1)].uid + '-app').emit('TASK-NEW')
        io.in(applyInfo.auditors['auditor' + (pos + 1)].uid + '-web').emit('TASK-CHANGE')
        io.in(applyInfo.auditors['auditor' + (pos + 1)].uid + '-web').emit('TASK-NEW')

        util.sendReminderSmsToUser(applyInfo.auditors['auditor' + (pos + 1)].uid, smsContent, '待审批')
    }

    // 更新任务状态 
    await mysqlUtil.execute('UPDATE tb_user_task SET sta = 1 WHERE id = ? LIMIT 1', [taskInfo.id])

    // 通知前端刷新角标
    io.in(socket.uid + '-app').emit('TASK-CHANGE')
    io.in(socket.uid + '-web').emit('TASK-CHANGE')

    callback({ code: 0, message: 'success' })
}

async function rejectTaskInfo(io, socket, params, taskInfo, callback) {

    let pos = taskInfo.pos

    let tb = ''
    let subject = ''
    if (taskInfo.typ == 0) { // 请假申请
        tb = 'tb_user_vacation_apply'
        subject = '请假申请'
    } else if (taskInfo.typ == 1) { // 出差申请
        tb = 'tb_user_chuchai_apply'
        subject = '出差申请'
    } else if (taskInfo.typ == 2) { // 加班申请
        tb = 'tb_jiaban_apply'
        subject = '加班申请'
    } else if (taskInfo.typ == 3) { // 入职申请
        tb = 'tb_entry_apply'
        subject = '入职申请'
    } else if (taskInfo.typ == 4) { // 转正申请
        tb = 'tb_user_zhuanzheng_apply'
        subject = '转正申请'
    } else if (taskInfo.typ == 5) { // 离职申请
        tb = 'tb_user_departure_apply'
        subject = '离职申请'
    } else if (taskInfo.typ == 6) { // 督办申请
        tb = 'tb_user_duban_apply'
        subject = '督办申请'
    } else if (taskInfo.typ == 7) { // 会议室申请
        tb = 'tb_meeting_room_apply'
        subject = '会议室申请'
    } else if (taskInfo.typ == 8) { // 接待申请
        tb = 'tb_user_jiedai_apply'
        subject = '接待单申请'
    } else if (taskInfo.typ == 9) { // 车辆加油
        tb = 'tb_user_jiayou_apply'
        subject = '车辆加油申请'
    } else if (taskInfo.typ == 10) { // 用车申请
        tb = 'tb_user_yongche_apply'
        subject = '用车申请'
    } else if (taskInfo.typ == 11) { // 用印申请
        tb = 'tb_user_yongyin_apply'
        subject = '用印申请'
    } else if (taskInfo.typ == 13) { // 采购申请
        tb = 'tb_user_caigou_apply'
        subject = '采购申请'
    } else if (taskInfo.typ == 14) { // 物资领用
        tb = 'tb_user_wuzilingyong_apply'
        subject = '物资领用申请'
    } else if (taskInfo.typ == 15) { // 合同审批
        tb = 'tb_user_hetong_shenpi'
        subject = '合同审批申请'
    } else if (taskInfo.typ == 16) { // 招标审核
        tb = 'tb_user_zhaobiao_shenhe'
        subject = '招标审核申请'
    } else if (taskInfo.typ == 17) { // 传阅文件
        tb = 'tb_user_chuanyue_apply'
        subject = '传阅文件申请'
    } else if (taskInfo.typ == 18) { // 文件流转
        tb = 'tb_user_liuzhuan_apply'
        subject = '文件流转申请'
    } else if (taskInfo.typ == 19) { // 补卡申请
        tb = 'tb_user_buka_apply'
        subject = '补卡申请'
    }

    // 查询申请信息
    let sql2 = 'SELECT * FROM ?? WHERE id = ? LIMIT 1'
    let res2 = await mysqlUtil.execute(sql2, [tb, taskInfo.relevenceId])
    if (res2.length == 0) return callback({ code: -1, message: '申请信息不存在' })
    let applyInfo = res2[0]
    // if (applyInfo.auditors['auditor' + pos].sta != 0) return callback({ code: -1, message: '申请已处理' })

    // 检查上个人拒绝了没
    if (applyInfo.auditors['auditor' + (pos - 1)] && applyInfo.auditors['auditor' + (pos - 1)].sta != 1) return callback({ code: -1, message: '申请已被拒绝' })

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 检查是不是重复处理的情况 重复处理的要看下个人是否处理了
    let auditors = applyInfo.auditors
    
    // 有下个审核人 判断下个审核人是不是处理了 没有下个审核人 则判断审核人是否都处理了
    if (auditors['auditor' + (pos + 1)]) {
        if (auditors['auditor' + (pos + 1)].sta != 0) return callback({ code: -1, message: '下个审核人已处理' })
    } else {
        let chengbanren = applyInfo.chengbanren || {}
        let chengbanDid = false
        for (let k in chengbanren) {
            if (chengbanren[k].sta != 0) {
                chengbanDid = true
                break
            }
        }

        if (chengbanDid) return callback({ code: -1, message: '流程已被处理' })

        applyInfo.chengbanren = {}
        await mysqlUtil.execute('UPDATE ?? SET chengbanren = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(applyInfo.chengbanren), taskInfo.relevenceId])
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // 更新用印申请单的审核信息
    applyInfo.auditors['auditor' + pos].sta = 2
    let sql3 = `UPDATE ?? SET auditors = JSON_SET(auditors, '$.auditor${pos}.sta', 2, '$.auditor${pos}.ts', ?, '$.auditor${pos}.msg', ?) WHERE id = ? LIMIT 1`
    let sql3Params = [tb, Date.now(), params.msg || '', taskInfo.relevenceId]
    await mysqlUtil.execute(sql3, sql3Params)

    // 如果是审核中的状态，且没有被撤销 则改变状态为失败，有1个拒绝就是失败
    // if (applyInfo.auditSta == 1) {
        await mysqlUtil.execute('UPDATE ?? SET auditSta = 3, sta = 2 WHERE id = ? LIMIT 1', [tb, applyInfo.id])

        // 插入通知
        await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
            uid: applyInfo.uid,
            typ: taskInfo.typ,
            title: '拒绝' + subject,
            content: taskInfo.name + '拒绝了你的' + subject,
            sta: 0,
            resTyp: 2,
            relevenceId: applyInfo.id,
            createTime: Date.now()
        }])

        // 通知给申请人
        io.in(applyInfo.uid + '-app').emit('NOTIFICATION-CHANGE')
        io.in(applyInfo.uid + '-app').emit('NOTIFICATION-NEW')
        io.in(applyInfo.uid + '-web').emit('NOTIFICATION-CHANGE')
        io.in(applyInfo.uid + '-web').emit('NOTIFICATION-NEW')

        // 通知前端刷新角标
        io.in(socket.uid + '-app').emit('TASK-CHANGE')
        io.in(socket.uid + '-web').emit('TASK-CHANGE')

        if (taskInfo.typ == 19) {
            if (applyInfo.bukaType == 1) {
                await mysqlUtil.execute('UPDATE tb_user_daka SET shangbanBukaSta = 3 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
            } else if (applyInfo.bukaType == 2) {
                await mysqlUtil.execute('UPDATE tb_user_daka SET xiabanBukaSta = 3 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
            }
        }
    // }

    // 更新任务状态
    await mysqlUtil.execute('UPDATE tb_user_task SET sta = 2 WHERE id = ? LIMIT 1', [params.id])

    callback({ code: 0, message: 'success' })
}

async function confirmTaskInfo(io, socket, params, taskInfo, callback) {
    let pos = taskInfo.pos

    let tb = ''
    let subject = ''
    if (taskInfo.typ == 0) { // 请假申请
        tb = 'tb_user_vacation_apply'
        subject = '请假申请'
    } else if (taskInfo.typ == 1) { // 出差申请
        tb = 'tb_user_chuchai_apply'
        subject = '出差申请'
    } else if (taskInfo.typ == 2) { // 加班申请
        tb = 'tb_jiaban_apply'
        subject = '加班申请'
    } else if (taskInfo.typ == 3) { // 入职申请
        tb = 'tb_entry_apply'
        subject = '入职申请'
    } else if (taskInfo.typ == 4) { // 转正申请
        tb = 'tb_user_zhuanzheng_apply'
        subject = '转正申请'
    } else if (taskInfo.typ == 5) { // 离职申请
        tb = 'tb_user_departure_apply'
        subject = '离职申请'
    } else if (taskInfo.typ == 6) { // 督办申请
        tb = 'tb_user_duban_apply'
        subject = '督办申请'
    } else if (taskInfo.typ == 7) { // 会议室申请
        tb = 'tb_meeting_room_apply'
        subject = '会议室申请'
    } else if (taskInfo.typ == 8) { // 接待申请
        tb = 'tb_user_jiedai_apply'
        subject = '接待单申请'
    } else if (taskInfo.typ == 9) { // 车辆加油
        tb = 'tb_user_jiayou_apply'
        subject = '车辆加油申请'
    } else if (taskInfo.typ == 10) { // 用车申请
        tb = 'tb_user_yongche_apply'
        subject = '用车申请'
    } else if (taskInfo.typ == 11) { // 用印申请
        tb = 'tb_user_yongyin_apply'
        subject = '用印申请'
    } else if (taskInfo.typ == 13) { // 采购申请
        tb = 'tb_user_caigou_apply'
        subject = '采购申请'
    } else if (taskInfo.typ == 14) { // 物资领用
        tb = 'tb_user_wuzilingyong_apply'
        subject = '物资领用申请'
    } else if (taskInfo.typ == 15) { // 合同审批
        tb = 'tb_user_hetong_shenpi'
        subject = '合同审批申请'
    } else if (taskInfo.typ == 16) { // 招标审核
        tb = 'tb_user_zhaobiao_shenhe'
        subject = '招标审核申请'
    } else if (taskInfo.typ == 17) { // 传阅文件
        tb = 'tb_user_chuanyue_apply'
        subject = '传阅文件申请'
    } else if (taskInfo.typ == 18) { // 文件流转
        tb = 'tb_user_liuzhuan_apply'
        subject = '文件流转申请'
    } else if (taskInfo.typ == 19) { // 补卡申请
        tb = 'tb_user_buka_apply'
        subject = '补卡申请'
    }

    // 查询申请信息
    let sql2 = 'SELECT * FROM ?? WHERE id = ? LIMIT 1'
    let res2 = await mysqlUtil.execute(sql2, [tb, taskInfo.relevenceId])
    if (res2.length == 0) return callback({ code: -1, message: '申请信息不存在' })
    let applyInfo = res2[0]
    applyInfo.chengbanren = applyInfo.chengbanren || {}
    // 只能处理自己的
    if (applyInfo.chengbanren['chengbanren' + pos].uid != socket.uid) return callback({ code: -1, message: '承办信息无法处理' })

    // 查询申请人的信息
    let sql4 = 'SELECT * FROM tb_user WHERE id = ? LIMIT 1'
    let res4 = await mysqlUtil.execute(sql4, [applyInfo.uid])
    if (res4.length == 0) return callback({ code: -1, message: '申请人信息不存在' })
    let applyUserInfo = res4[0]

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 处理第二次确认的情况
    if (taskInfo.typ == 17) { // 传阅文件
        let chengbanren = applyInfo.chengbanren
        if (!chengbanren || !chengbanren['chengbanren' + pos]) return callback({code: -1, message: "无此承办步骤"})

        let chengbanTotal = 0
        while(chengbanren['chengbanren' + chengbanTotal]) {
            chengbanTotal++
        }

        // 不是最后一个人 要看周莉处理了没
        if (pos != chengbanTotal - 1 && chengbanren['chengbanren' + (chengbanTotal - 1)].sta != 0) {
            return callback({code: -1, message: "已分发，无法重新编辑"})
        }
    } else if (taskInfo.typ == 18) { // 文件流转
        let chengbanren = applyInfo.chengbanren
        if (!chengbanren || !chengbanren['chengbanren' + pos]) return callback({code: -1, message: "无此承办步骤"})

        let zhouliDid = false
        let zhouliIdx = -1
        let departDid = false

        let chengbanTotal = 0
        while(chengbanren['chengbanren' + chengbanTotal]) {
            if (chengbanren['chengbanren' + chengbanTotal].selectDepart) {
                zhouliIdx = chengbanTotal
                if (chengbanren['chengbanren' + chengbanTotal].sta) {
                    zhouliDid = true
                }
            }
            if (chengbanren['chengbanren' + chengbanTotal].departId && chengbanren['chengbanren' + chengbanTotal].sta) {
                departDid = true
            }
            chengbanTotal++
        }

        // 分管领导想撤回 但是周莉处理了 无法撤回
        if (chengbanren['chengbanren' + pos].fenguan && zhouliDid) return callback({code: -1, message: "已分发，无法重新编辑"})
        // 周莉想撤回 但是部门领导处理了 无法撤回
        if (chengbanren['chengbanren' + pos].selectDepart && departDid) return callback({code: -1, message: "已处理，无法撤回"})

        // 如果是周莉想撤回 需要把部门领导都去掉
        if (pos == zhouliIdx) {
            let newChengbanren = {}
            for (let i = 0; i <= zhouliIdx; i++) {
                newChengbanren['chengbanren' + i] = chengbanren['chengbanren' + i]
            }
            applyInfo.chengbanren = newChengbanren
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    // if (applyInfo.chengbanren['chengbanren' + pos].sta != 0) return callback({ code: -1, message: '承办信息已确认' })

    applyInfo.chengbanren['chengbanren' + pos].sta = 1
    applyInfo.chengbanren['chengbanren' + pos].ts = Date.now()
    applyInfo.chengbanren['chengbanren' + pos].msg = params.msg || ''

    let users = params.users || []
    let departs = params.departs || []
    // 督办单 所有承办人 选择具体承办人 并发送通知
    if (taskInfo.typ == 6) {
        for (let i = 0; i != users.length; i++) {
            // 插入通知
            await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                uid: users[i].uid,
                typ: taskInfo.typ,
                title: '督办单',
                content: params.msg || applyUserInfo.name + '的督办单申请已通过，请注意跟进',
                sta: 0,
                resTyp: 3,
                relevenceId: applyInfo.id,
                createTime: Date.now()
            }])
            // 通知给具体承办人
            io.in(users[i].uid + '-app').emit('NOTIFICATION-CHANGE')
            io.in(users[i].uid + '-app').emit('NOTIFICATION-NEW')
            io.in(users[i].uid + '-web').emit('NOTIFICATION-CHANGE')
            io.in(users[i].uid + '-web').emit('NOTIFICATION-NEW')

            util.sendReminderSmsToUser(users[i].uid, '督办单', '待跟进')
        }
        applyInfo.chengbanren['chengbanren' + pos].jingbanren = users
    }
    // 会议室 第一个承办人 选择具体承办人 并发送通知
    if (taskInfo.typ == 7 && taskInfo.pos == 0) {
        let msg = '具体经办人:' + users.map(item => item.name).join(',')
        for (let i = 0; i != users.length; i++) {
            // 插入通知
            await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                uid: users[i].uid,
                typ: taskInfo.typ,
                title: '会议室申请',
                content: applyUserInfo.name + '的会议室申请已通过，请注意跟进',
                sta: 0,
                resTyp: 3,
                relevenceId: applyInfo.id,
                createTime: Date.now()
            }])
            // 通知给具体承办人
            io.in(users[i].uid + '-app').emit('NOTIFICATION-CHANGE')
            io.in(users[i].uid + '-app').emit('NOTIFICATION-NEW')
            io.in(users[i].uid + '-web').emit('NOTIFICATION-CHANGE')
            io.in(users[i].uid + '-web').emit('NOTIFICATION-NEW')

            util.sendReminderSmsToUser(users[i].uid, '会议室申请', '待跟进')
        }
        await mysqlUtil.execute('UPDATE ?? SET sta = 1, dabaoren = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(users), taskInfo.relevenceId])
        applyInfo.chengbanren['chengbanren' + pos].msg = msg
    }
    // 传阅文件 第3个承办人 添加读者 并发送通知
    logger.debug("before 17", taskInfo)
    if (taskInfo.typ == 17 && taskInfo.uid == 10) {
        logger.debug('传阅文件 第3个承办人 添加读者 并发送通知', users)
        // 公文流转和传阅文件需要添加文件名
        for (let i = 0; i != users.length; i++) {
            // 插入通知
            await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                uid: users[i].uid,
                typ: 17,
                title: applyInfo.biaoti,
                content: applyInfo.biaoti,
                sta: 0,
                resTyp: 3,
                relevenceId: taskInfo.relevenceId,
                createTime: Date.now()
            }])

            // 传阅文件 需要将读者添加到传阅文件关联表中
            await mysqlUtil.execute('INSERT INTO tb_user_chuanyue_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                uid: users[i].uid,
                relevenceId: applyInfo.id,
                updateTime: Date.now()
            }, Date.now()])

            // 通知给申请人
            io.in(users[i].uid + '-app').emit('NOTIFICATION-CHANGE')
            io.in(users[i].uid + '-app').emit('NOTIFICATION-NEW')
            io.in(users[i].uid + '-web').emit('NOTIFICATION-CHANGE')
            io.in(users[i].uid + '-web').emit('NOTIFICATION-NEW')

            let smsContent = '传阅文件申请'
            let file1Name = ''
            let attaches = applyInfo.attaches || []
            if (attaches.length > 0) {
                file1Name = attaches[0].name
            }
            if (file1Name) {
                if (file1Name.length > 20) {
                    file1Name = file1Name.slice(0, 19) + '...'
                }
                smsContent = smsContent + '【' + file1Name + '】'
            }

            util.sendReminderSmsToUser(users[i].uid, smsContent, '待跟进')

        }
        let readers = applyInfo.readers || []
        readers = readers.concat(users)
        await mysqlUtil.execute('UPDATE ?? SET readers = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(readers), taskInfo.relevenceId])
        applyInfo.readers = readers
    }
    // 公文流转
    if (taskInfo.typ == 18) {

        // 分管领导选择责任部门 发送任务给责任部门领导
        if (applyInfo.chengbanren['chengbanren' + taskInfo.pos].fenguan) {

            // 所有的分管领导都结束 把陈浩宇加入进来
            let fenguanOver = true
            for (let k in applyInfo.chengbanren) {
                if (!applyInfo.chengbanren[k].sta) {
                    fenguanOver = false
                    break
                }
            }
            if (fenguanOver) {
                let idx = Object.getOwnPropertyNames(applyInfo.chengbanren).length
                applyInfo.chengbanren['chengbanren' + idx] = {}
                applyInfo.chengbanren['chengbanren' + idx].uid = 10
                applyInfo.chengbanren['chengbanren' + idx].name = '陈皓玉'
                applyInfo.chengbanren['chengbanren' + idx].positionName = '行政助理'
                applyInfo.chengbanren['chengbanren' + idx].sta = 0
                applyInfo.chengbanren['chengbanren' + idx].selectDepart = 1

                // 发送任务
                await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ? AND isChengban = ?', [taskInfo.typ, applyInfo.id, idx, 1])
                logger.info('承办删除任务5', [taskInfo.typ, applyInfo.id, idx, 1])
                await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
                    uid: 10,
                    typ: taskInfo.typ,
                    relevenceId: applyInfo.id,
                    title: applyInfo.biaoti,
                    pos: idx,
                    isChengban: 1,
                    content: applyInfo.biaoti,
                    sta: 0,
                    createTime: Date.now()
                }])
                io.in( 10 + '-app').emit('TASK-CHANGE')
                io.in( 10 + '-app').emit('TASK-NEW')
                io.in( 10 + '-web').emit('TASK-CHANGE')
                io.in( 10 + '-web').emit('TASK-NEW')

                // 公文流转 需要添加到公文流转关联表中
                await mysqlUtil.execute('INSERT INTO tb_user_liuzhuan_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                    uid: 10,
                    relevenceId: applyInfo.id,
                    updateTime: Date.now()
                }, Date.now()])

                let smsContent = '公文流转'
                let file1Name = ''
                let attaches = applyInfo.attaches || []
                if (attaches.length > 0) {
                    file1Name = attaches[0].name
                }
                if (file1Name) {
                    if (file1Name.length > 20) {
                        file1Name = file1Name.slice(0, 19) + '...'
                    }
                    smsContent = smsContent + '【' + file1Name + '】'
                }

                util.sendReminderSmsToUser(10, smsContent, '选择承办部门')
            }
        } else if (applyInfo.chengbanren['chengbanren' + taskInfo.pos].selectDepart) { // 选择承办部门
            for (let i = 0; i != departs.length; i++) {
                let idx = Object.getOwnPropertyNames(applyInfo.chengbanren).length
                applyInfo.chengbanren['chengbanren' + idx] = {}
                applyInfo.chengbanren['chengbanren' + idx].uid = departs[i].departLingdao
                applyInfo.chengbanren['chengbanren' + idx].departId = departs[i].departId
                applyInfo.chengbanren['chengbanren' + idx].name = departs[i].departLingdaoName
                applyInfo.chengbanren['chengbanren' + idx].positionName = departs[i].departName
                applyInfo.chengbanren['chengbanren' + idx].sta = 0

                // 发送任务
                await mysqlUtil.execute('DELETE FROM tb_user_task WHERE typ = ? AND relevenceId = ? AND pos = ? AND isChengban = ?', [taskInfo.typ, applyInfo.id, idx, 1])
                logger.info('承办删除任务6', [taskInfo.typ, applyInfo.id, idx, 1])
                await mysqlUtil.execute('INSERT INTO tb_user_task SET ?', [{
                    uid: departs[i].departLingdao,
                    typ: taskInfo.typ,
                    relevenceId: applyInfo.id,
                    title: applyInfo.biaoti,
                    pos: idx,
                    isChengban: 1,
                    content: applyInfo.biaoti,
                    sta: 0,
                    createTime: Date.now()
                }])
                io.in( departs[i].departLingdao + '-app').emit('TASK-CHANGE')
                io.in( departs[i].departLingdao + '-app').emit('TASK-NEW')
                io.in( departs[i].departLingdao + '-web').emit('TASK-CHANGE')
                io.in( departs[i].departLingdao + '-web').emit('TASK-NEW')

                // 公文流转 需要添加到公文流转关联表中
                await mysqlUtil.execute('INSERT INTO tb_user_liuzhuan_relevence SET ? ON DUPLICATE KEY UPDATE updateTime = ? ', [{
                    uid: departs[i].departLingdao,
                    relevenceId: applyInfo.id,
                    updateTime: Date.now()
                }, Date.now()])

                let smsContent = '公文流转'
                let file1Name = ''
                let attaches = applyInfo.attaches || []
                if (attaches.length > 0) {
                    file1Name = attaches[0].name
                }
                if (file1Name) {
                    if (file1Name.length > 20) {
                        file1Name = file1Name.slice(0, 19) + '...'
                    }
                    smsContent = smsContent + '【' + file1Name + '】'
                }

                util.sendReminderSmsToUser(departs[i].departLingdao, smsContent, '待跟进')
            }
        } else { // 其它选择经办人 发送任务
            for (let i = 0; i != users.length; i++) {
                // 插入通知
                await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
                    uid: users[i].uid,
                    typ: taskInfo.typ,
                    title: applyInfo.biaoti,
                    content: applyInfo.biaoti,
                    sta: 0,
                    resTyp: 3,
                    relevenceId: taskInfo.relevenceId,
                    createTime: Date.now()
                }])

                // 通知给申请人
                io.in(users[i].uid + '-app').emit('NOTIFICATION-CHANGE')
                io.in(users[i].uid + '-app').emit('NOTIFICATION-NEW')
                io.in(users[i].uid + '-web').emit('NOTIFICATION-CHANGE')
                io.in(users[i].uid + '-web').emit('NOTIFICATION-NEW')

                let smsContent = '公文流转'
                let file1Name = ''
                let attaches = applyInfo.attaches || []
                if (attaches.length > 0) {
                    file1Name = attaches[0].name
                }
                if (file1Name) {
                    if (file1Name.length > 20) {
                        file1Name = file1Name.slice(0, 19) + '...'
                    }
                    smsContent = smsContent + '【' + file1Name + '】'
                }
                util.sendReminderSmsToUser(users[i].uid, smsContent, '待跟进')
            }
            let readers = applyInfo.readers || []
            readers = readers.concat(users)
            await mysqlUtil.execute('UPDATE ?? SET readers = ? WHERE id = ? LIMIT 1', [tb, JSON.stringify(readers), taskInfo.relevenceId])
            applyInfo.readers = readers
        }
    }

    let sql3 = 'UPDATE ?? SET chengbanren = ? WHERE id = ? LIMIT 1'
    await mysqlUtil.execute(sql3, [tb, JSON.stringify(applyInfo.chengbanren), taskInfo.relevenceId])

    let allPass = true
    for (let key in applyInfo.chengbanren) {
        if (applyInfo.chengbanren[key].sta != 1) {
            allPass = false
            break
        }
    }

    // 承办流程已结束 任务完成
    if (allPass) {

        let content = '所有的审批已通过，' + subject + '审核已通过'
        if (taskInfo.typ == 17 || taskInfo.typ == 18) {
            content = applyInfo.biaoti
        }

        // 更新申请的承办状态
        await mysqlUtil.execute('UPDATE ?? SET chengbanSta = 2, sta = 1 WHERE id = ? LIMIT 1', [tb, applyInfo.id])

        // 插入通知
        await mysqlUtil.execute('INSERT INTO tb_user_notification SET ?', [{
            uid: applyInfo.uid, // 请假人的uid
            typ: taskInfo.typ,
            title: subject + '审核通过',
            content,
            sta: 0,
            resTyp: 3,
            relevenceId: applyInfo.id,
            createTime: Date.now()
        }])

        // 通知给申请人
        io.in(applyInfo.uid + '-app').emit('NOTIFICATION-CHANGE')
        io.in(applyInfo.uid + '-app').emit('NOTIFICATION-NEW')
        io.in(applyInfo.uid + '-web').emit('NOTIFICATION-CHANGE')
        io.in(applyInfo.uid + '-web').emit('NOTIFICATION-NEW')

        // 处理需要展开的项
        if (taskInfo.typ == 0) { // 请假要展开 开始时间和结束时间按天进行分割
            let infos = applyInfo.detail || []
            let uid = applyInfo.uid
            for (let i = 0; i != infos.length; i++) {
                let day = infos[i].day
                // 查询当天有没有打卡记录 没有则插入
                let rr = await mysqlUtil.execute('SELECT qingjiaInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [uid, day])
                if (rr.length == 0) {
                    let dakaInfo = { uid, day }
                    await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                }
                let qingjiaInfo = {start: infos[i].start, end: infos[i].end}

                // 更新请假信息
                await mysqlUtil.execute('UPDATE tb_user_daka SET qingjiaInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(qingjiaInfo), uid, day])
            }
        } else if (taskInfo.typ == 1) { // 出差要展开 展开到打卡信息中
            for (let i = 0; i != applyInfo.days; i++) {
                let chuchairen = applyInfo.chuchairen || []
                for (let j = 0; j != chuchairen.length; j++) {
                    let uid = chuchairen[j].uid
                    let day = moment(applyInfo.startDate).add(i, 'day').format('YYYY-MM-DD')
                    // 查询当天有没有打卡记录 没有则插入
                    let rr = await mysqlUtil.execute('SELECT chuchaiInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [uid, day])
                    if (rr.length == 0) {
                        let dakaInfo = { uid, day }
                        await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                    }
                    let chuchaiInfo = {id: applyInfo.id, start: moment(day).startOf('day').format('HH:mm:ss'), end: moment(day).endOf('day').format('HH:mm:ss')}
                    // 更新出差信息
                    await mysqlUtil.execute('UPDATE tb_user_daka SET chuchaiInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(chuchaiInfo), uid, day])
                }
            }
        } else if (taskInfo.typ == 2) { // 加班要展开 并通知加班人
            let attenders = applyInfo.attenders
            for (let i = 0; i != attenders.length; i++) {

                let jiabanUid = attenders[i].uid
                let day = moment(applyInfo.startTime).format('YYYY-MM-DD')
                // 查询当天有没有打卡记录 没有则插入
                let rr = await mysqlUtil.execute('SELECT jiabanInfo FROM tb_user_daka WHERE uid = ? AND day = ? LIMIT 1', [jiabanUid, day])
                if (rr.length == 0) {
                    let dakaInfo = { uid: jiabanUid, day }
                    await mysqlUtil.execute('INSERT INTO tb_user_daka SET ?', [dakaInfo])
                }
                let jiabanInfo = {start: moment(applyInfo.startTime).format('YYYY-MM-DD HH:mm:ss'), end: moment(applyInfo.endTime).format('YYYY-MM-DD HH:mm:ss')}

                // 更新加班信息
                await mysqlUtil.execute('UPDATE tb_user_daka SET jiabanInfo = ? WHERE uid = ? AND day = ? LIMIT 1', [JSON.stringify(jiabanInfo), uid, day])
            }
        } else if (taskInfo.typ == 19) { // 补卡申请设置为审核通过状态
            if (applyInfo.bukaType == 1) {
                await mysqlUtil.execute('UPDATE tb_user_daka SET shangbanBukaSta = 2 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
            } else if (applyInfo.bukaType == 2) {
                await mysqlUtil.execute('UPDATE tb_user_daka SET xiabanBukaSta = 2 WHERE id = ? LIMIT 1', [applyInfo.relevenceId])
            }
        } else if (taskInfo.typ == 17 || taskInfo.typ == 18) { // 传阅文件和公文流转要添加到历史公文中
            let uids = []
            for (let k in applyInfo.auditors) {
                if (uids.indexOf(applyInfo.auditors[k].uid) != -1) continue
                uids.push(applyInfo.auditors[k].uid)
            }

            for (let k in applyInfo.chengbanren) {
                if (uids.indexOf(applyInfo.chengbanren[k].uid) != -1) continue
                uids.push(applyInfo.chengbanren[k].uid)
            }

            for (let i = 0; i != applyInfo.readers.length; i++) {
                if (uids.indexOf(applyInfo.readers[i].uid) != -1) continue
                uids.push(applyInfo.readers[i].uid)
            }

            for (let i = 0; i != uids.length; i++) {
                let uid = uids[i]
                // let content = applyInfo.zhaiyao
                // let attaches = applyInfo.attaches || []
                // for (let j = 0; j != attaches.length; j++) {
                //     content += '<br>'
                //     content += attaches[j].name
                // }
                await mysqlUtil.execute('INSERT INTO tb_user_gongwen_history SET ?', [{
                    uid,
                    title: applyInfo.biaoti,
                    content: applyInfo.zhaiyao || applyInfo.biaoti,
                    relevenceId: applyInfo.id,
                    typ: taskInfo.typ,
                    fileTag: applyInfo.fileTag || 0,
                    gongwenTime: applyInfo.createTime,
                    createTime: Date.now()
                }])
            }
        }
    }

    // 更新任务状态 
    await mysqlUtil.execute('UPDATE tb_user_task SET sta = 1 WHERE id = ? LIMIT 1', [taskInfo.id])

    // 通知前端刷新角标
    io.in(socket.uid + '-app').emit('TASK-CHANGE')
    io.in(socket.uid + '-web').emit('TASK-CHANGE')

    callback({ code: 0, message: 'success' })
}

module.exports = {

    getLingdao,

    // 获取未完成的任务数量
    getUnfinishedTaskCnt: async (io, socket, params, callback) => {

        let uid = socket.uid
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        callback = callback || commonModule.emptyFunc

        try {
            let sql = 'SELECT COUNT(1) cnt FROM tb_user_task WHERE uid = ? AND sta = 0'
            let res = await mysqlUtil.execute(sql, [uid])
            callback({ code: 0, message: 'success', data: res[0].cnt })
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 获取任务列表
    getTaskList: async (io, socket, params, callback) => {

        let uid = socket.uid
        callback = callback || commonModule.emptyFunc
        if (!uid) return callback({ code: 9999, message: '请重新登录' })


        // 小于的id
        let lessThan = params.lessThan || 0
        // 大于的id
        let greaterThan = params.greaterThan || 0
        // 每页的数量
        let pageCount = params.pageCount || 10

        logger.debug('get task list', lessThan, greaterThan, pageCount)

        try {
            let sql = ''
            let sqlParams = []
            if (lessThan) {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND id < ? ORDER BY sta ASC, id DESC LIMIT ?'
                sqlParams = [uid, lessThan, pageCount]
            } else if (greaterThan) {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND id > ? ORDER BY sta ASC, id DESC LIMIT ?'
                sqlParams = [uid, greaterThan, pageCount]
            } else {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? ORDER BY sta ASC, id DESC LIMIT ?'
                sqlParams = [uid, pageCount]
            }
            let res = await mysqlUtil.execute(sql, sqlParams)
            callback({ code: 0, message: 'success', data: res })
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 获取任务详情
    getTaskDetail: async (io, socket, params, callback) => {
        let uid = socket.uid
        callback = callback || commonModule.emptyFunc
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        if (!params.id) return callback({code: -1, message: '参数缺失'})

        try {
            let res = await mysqlUtil.execute('SELECT * FROM tb_user_task WHERE id = ? LIMIT 1', [params.id])
            if (res.length == 0) return callback({code: -1, message: '不存在'})
            callback({code: 0, message: '', data: res[0]})
        } catch (err) {
            logger.error(err)
            callback({code: -1, message: "system error"})
        }
    },

    getTaskListWeb: async (io, socket, params, callback) => {

        let uid = socket.uid
        callback = callback || commonModule.emptyFunc
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        let pageIndex = parseInt(params.pageIndex || 1);
        let pageCount = parseInt(params.pageCount || 10);

        try {
            // 总数
            let res = await mysqlUtil.execute('SELECT COUNT(1) cnt FROM tb_user_task WHERE uid = ?', [uid])
            let count = res[0].cnt
            // 未完成
            res = await mysqlUtil.execute('SELECT COUNT(1) cnt FROM tb_user_task WHERE uid = ? AND sta = 0', [uid])
            let unRead = res[0].cnt
            // 列表
            let sql = 'SELECT * FROM tb_user_task WHERE uid = ? ORDER BY sta ASC, id DESC LIMIT ?, ?'
            let params = [uid, (pageIndex - 1) * pageCount, pageCount]
            res = await mysqlUtil.execute(sql, params)
            callback({ code: 0, message: 'success', data: { list: res, count, unRead } })
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 获取任务带列表带状态web
    getTaskListWithStatusWeb: async (io, socket, params, callback) => {
        let uid = socket.uid
        callback = callback || commonModule.emptyFunc
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        let status = params.status || 0
        if (status !== 0 && status !== 1) {
            return callback({ code: -1, message: '参数错误' })
        }

        let pageNum = parseInt(params.pageNum || 1);
        let pageSize = parseInt(params.pageSize || 10);

        try {
            // 查询总数
            let res = await mysqlUtil.execute('SELECT COUNT(1) cnt FROM tb_user_task WHERE uid = ? AND sta = ?', [uid, status])
            let count = res[0].cnt

            // 查询数据
            res = await mysqlUtil.execute('SELECT * FROM tb_user_task WHERE uid = ? AND sta = ? ORDER BY id DESC LIMIT ?, ?', [uid, status, (pageNum - 1) * pageSize, pageSize])

            callback({code: 0, message: 'success', data: {list: res, count}})
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error'})
        }
    },

    // 获取已完成任务列表
    getTaskListYiwancheng: async (io, socket, params, callback) => {

        let uid = socket.uid
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        callback = callback || commonModule.emptyFunc

        // 小于的id
        let lessThan = params.lessThan || 0
        // 大于的id
        let greaterThan = params.greaterThan || 0
        // 每页的数量
        let pageCount = params.pageCount || 10

        logger.debug('get task list', lessThan, greaterThan, pageCount)

        try {
            let sql = ''
            let sqlParams = []
            if (lessThan) {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND sta in (?) AND id < ? ORDER BY id DESC LIMIT ?'
                sqlParams = [uid, [1, 2], lessThan, pageCount]
            } else if (greaterThan) {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND sta in (?) AND id > ? ORDER BY id DESC LIMIT ?'
                sqlParams = [uid, [1, 2], greaterThan, pageCount]
            } else {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND sta in (?) ORDER BY id DESC LIMIT ?'
                sqlParams = [uid, [1, 2], pageCount]
            }
            let res = await mysqlUtil.execute(sql, sqlParams)
            callback({ code: 0, message: 'success', data: res })
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 获取未完成任务列表
    getTaskListWeiwancheng: async (io, socket, params, callback) => {

        let uid = socket.uid
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        callback = callback || commonModule.emptyFunc

        // 小于的id
        let lessThan = params.lessThan || 0
        // 大于的id
        let greaterThan = params.greaterThan || 0
        // 每页的数量
        let pageCount = params.pageCount || 10

        logger.debug('get task list', lessThan, greaterThan, pageCount)

        try {
            let sql = ''
            let sqlParams = []
            if (lessThan) {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND sta = 0 AND id < ? ORDER BY id DESC LIMIT ?'
                sqlParams = [uid, lessThan, pageCount]
            } else if (greaterThan) {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND sta = 0 AND id > ? ORDER BY id DESC LIMIT ?'
                sqlParams = [uid, greaterThan, pageCount]
            } else {
                sql = 'SELECT * FROM tb_user_task WHERE uid = ? AND sta = 0 ORDER BY id DESC LIMIT ?'
                sqlParams = [uid, pageCount]
            }
            let res = await mysqlUtil.execute(sql, sqlParams)
            callback({ code: 0, message: 'success', data: res })
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 同意任务
    agreeTask: async (io, socket, params, callback) => {

        let uid = socket.uid
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        callback = callback || commonModule.emptyFunc

        if (!params.id) return callback({ code: -1, message: '参数缺失' })

        logger.debug('agree task1', params)

        try {

            // 先加个1秒钟的锁
            let lockKey = 'LOCK:AGREE:TASK:' + uid
            await redisUtil.setLock(lockKey, 2)

            // 查询任务信息
            let sql1 = `
                SELECT
                    tb_user_task.id,
                    tb_user_task.sta,
                    tb_user_task.typ,
                    tb_user_task.pos,
                    tb_user_task.relevenceId,
                    tb_user.name
                FROM
                    tb_user_task
                    INNER JOIN tb_user ON tb_user.uid = tb_user_task.uid
                WHERE
                    tb_user_task.id = ?
                LIMIT 1
            `
            let res1 = await mysqlUtil.execute(sql1, [params.id])
            if (res1.length == 0) return callback({ code: -1, message: '任务不存在' })
            // if (res1[0].sta != 0) return callback({ code: -1, message: '任务已经处理' })
            logger.debug('agree task2', res1[0])

            return await agreeTaskInfo(io, socket, params, res1[0], callback)
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 拒绝任务
    rejectTask: async (io, socket, params, callback) => {

        let uid = socket.uid
        callback = callback || commonModule.emptyFunc
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        if (!params.id) return callback({ code: -1, message: '参数缺失' })

        logger.debug('reject task1', params)

        try {
            // 查询任务信息
            let sql1 = `
                SELECT
                    tb_user_task.id,
                    tb_user_task.sta,
                    tb_user_task.typ,
                    tb_user_task.pos,
                    tb_user_task.relevenceId,
                    tb_user.name
                FROM
                    tb_user_task
                    INNER JOIN tb_user ON tb_user.uid = tb_user_task.uid
                WHERE
                    tb_user_task.id = ?
                LIMIT 1
            `
            let res1 = await mysqlUtil.execute(sql1, [params.id])
            if (res1.length == 0) return callback({ code: -1, message: '任务不存在' })
            // if (res1[0].sta != 0) return callback({ code: -1, message: '任务已经处理' })
            logger.debug('reject task2', res1[0])

            return await rejectTaskInfo(io, socket, params, res1[0], callback)
        } catch (err) {
            logger.error(err)
            callback({ code: -1, message: 'system error' })
        }
    },

    // 确认任务执行
    confirmTask: async (io, socket, params, callback) => {
        let uid = socket.uid
        callback = callback || commonModule.emptyFunc
        if (!uid) return callback({ code: 9999, message: '请重新登录' })

        logger.debug('confirm task11', params)

        if (!params.id) return callback({ code: -1, message: '参数缺失' })

        try {
            // 查询任务信息
            let sql1 = `
                SELECT
                    tb_user_task.id,
                    tb_user_task.uid,
                    tb_user_task.sta,
                    tb_user_task.typ,
                    tb_user_task.pos,
                    tb_user_task.relevenceId,
                    tb_user.name
                FROM
                    tb_user_task
                    INNER JOIN tb_user ON tb_user.uid = tb_user_task.uid
                WHERE
                    tb_user_task.id = ?
                LIMIT 1
            `
            let res1 = await mysqlUtil.execute(sql1, [params.id])
            if (res1.length == 0) return callback({ code: -1, message: '任务不存在' })
            // if (res1[0].sta != 0) return callback({ code: -1, message: '任务已经处理' })
            logger.debug('confirm task22', res1[0])

            return await confirmTaskInfo(io, socket, params, res1[0], callback)
        } catch (err) {
            logger.error(err)
            callback({code: -1, message: 'system error'})
        }
    },


    // 撤销审批
    /*
    0请假申请
    1出差申请
    2加班申请
    5离职申请
    6督办单
    7会议室申请
    8接待单申请
    9车辆加油
    10用车申请
    11用印申请
    13采购单申请
    14物资领用申请
    15合同审批
    16招标文件审核
    17传阅文件
    18公文流转
    */
    revertAudit: async (io, socket, params, callback) => {
        
    }
}